package com.lx.chat.web;



import com.lx.chat.biz.IMsgSender;
import com.lx.chat.web.vo.Msg;
import com.lx.chat.web.vo.WebsocktPropertise;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@RestController
@RequestMapping("vws")
// 地址 当浏览器链接服务器所需要的地址
@ServerEndpoint(value = "/video/vws/{vid}/{id}")
public class VideoWebsocktDo{

    // 在每一次链接的时候 VideoWebsocktDo 对象 都会被创建一次
    static WebsocktPropertise Propertise;
    static IMsgSender iMsgSender;
    static JdbcTemplate jdbcTemplate;

    @Autowired
    public void setiMsgSender(IMsgSender iMsgSender) {
        VideoWebsocktDo.iMsgSender = iMsgSender;
    }

    @Autowired
    public void setPropertise(WebsocktPropertise propertise) {
        VideoWebsocktDo.Propertise = propertise;
    }

    @Autowired
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        VideoWebsocktDo.jdbcTemplate = jdbcTemplate;
    }

    @GetMapping("config")
    WebsocktPropertise websocktPropertise(){

        return Propertise;
    }


    // websocket 会为每个连接成功的客服端创建一个 talkdo 对象

    // 在线用户的容器
    private static Map<String, Set<Session>> onlines = new ConcurrentHashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("vid") String vid, @PathParam("id") String id) throws Exception {
        System.out.println("连接成功");
        Object userinfo = getUserInfoById(id);
        session.getUserProperties().put(id, userinfo);
        if(onlines.containsKey(vid)){
            onlines.get(vid).add(session);
        }else{
            Set<Session> sessions = new HashSet<>();
            sessions.add(session);
            onlines.put(vid, sessions);
        }
        System.out.println("onlines" + onlines.get(vid));
        Msg msg = buildMsg(userinfo, "", true, vid);
        iMsgSender.Vsend(msg,vid);
    }

    @OnClose
    public void onClose(Session session, @PathParam("vid") String vid, @PathParam("id") String id) throws Exception {
        System.out.println("vid = " + vid);
        Map<String, Object> userinfo = (Map<String, Object>) session.getUserProperties().get(id);
        onlines.get(vid).remove(session);
        System.out.println("onlines" + onlines.get(vid));
        Msg msg = buildMsg(userinfo, "", true, vid);
        iMsgSender.Vsend(msg, vid);
    }

    @OnError
    public void OnError(Session session, Throwable throwable) {
        System.out.println("会话异常:" + throwable);
    }

    // 当接收到客户端发送的信息时触发的方法
    @OnMessage
    public void OnMessage(Session session, String message,@PathParam("vid") String vid, @PathParam("id") String id) throws Exception {
        Object userinfo = session.getUserProperties().get(id);
        Msg msg = buildMsg(userinfo, message, false, vid);
        iMsgSender.Vsend(msg, vid);
    }



    public Msg buildMsg(Object author, String content, boolean isOnlines, String vid){
        Msg msg = new Msg(author, content, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),null, onlines.get(vid).size()); //
        if(isOnlines == true){
            // 一个包含 所有在线用户 id 的一个集合
            List<Object> onlinesMap = onlines.get(vid).
                    stream().
                    map(session -> session.getUserProperties().get("id")).
                    collect(Collectors.toList());
            msg.setOnlines(onlinesMap);
        }
        return msg;
    }




//    @Data
//    @AllArgsConstructor
//    @NoArgsConstructor
//    public static class Msg{
//
//        // 发送人
//        Object author;
//        // 内容
//        String content;
//        // 时间
//        String time;
//        // 下线人员列表
//        List<Object> onlines;
//
//        // 这里为什么不用类对象, 应为存入session中的数据是传给前端的, 所以不需要, 之前用类对象是因为那些用户数据是给后端用的
//    }

    // 获取在线人数的集合
    public static Map<String, Set<Session>> getOnlines() {
        return onlines;
    }

    private Object getUserInfoById(String id) {
        String sql = "select * from %s where %s = ? ";
        sql = String.format(sql, websocktPropertise().getUserTable(), websocktPropertise().getKeyColumn());
        Map<String, Object> userinfo = jdbcTemplate.queryForMap(sql, id);
        return userinfo;
    }

}
